package org.budo.jdbc.driver.parser;

import java.sql.SQLException;

import org.budo.jdbc.driver.statement.JdbcStatement;
import org.budo.jdbc.driver.statement.impl.SELECT_AT_AT;
import org.budo.jdbc.driver.statement.impl.SELECT_INFORMATION_SCHEMA;
import org.budo.jdbc.driver.statement.impl.SELECT_ONE;
import org.budo.jdbc.driver.statement.impl.SET_NAMES;
import org.budo.jdbc.driver.statement.impl.SHOW_CHARACTER_SET;
import org.budo.jdbc.driver.statement.impl.SHOW_COLUMNS;
import org.budo.jdbc.driver.statement.impl.SHOW_CREATE_TABLE;
import org.budo.jdbc.driver.statement.impl.SHOW_ENGINES;
import org.budo.jdbc.driver.statement.impl.SHOW_FUNCTION_STATUS;
import org.budo.jdbc.driver.statement.impl.SHOW_PROCEDURE_STATUS;
import org.budo.jdbc.driver.statement.impl.SHOW_STATUS;
import org.budo.jdbc.driver.statement.impl.SHOW_VARIABLES;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
public abstract class AbstractSqlStatementParser implements SqlStatementParser {
    public JdbcStatement parse(String sql) throws SQLException {
        try {
            String sqlTrimUpper = sql.trim().toUpperCase();
            if (sqlTrimUpper.startsWith("SELECT @@")) {
                return new SELECT_AT_AT();
            }

            if (sqlTrimUpper.equalsIgnoreCase("SELECT 1")) {
                return new SELECT_ONE();
            }

            if (sqlTrimUpper.startsWith("SHOW VARIABLES LIKE")) {
                return new SHOW_VARIABLES();
            }

            if (sqlTrimUpper.startsWith("SHOW STATUS")) {
                return new SHOW_STATUS();
            }

            if (sqlTrimUpper.startsWith("SHOW ENGINES")) {
                return new SHOW_ENGINES();
            }

            if (sqlTrimUpper.startsWith("SHOW CREATE TABLE")) {
                return new SHOW_CREATE_TABLE();
            }

            if (sqlTrimUpper.startsWith("SHOW COLUMNS FROM")) {
                return new SHOW_COLUMNS();
            }

            if (sqlTrimUpper.startsWith("SHOW PROCEDURE STATUS")) {
                return new SHOW_PROCEDURE_STATUS();
            }

            if (sqlTrimUpper.startsWith("SHOW CHARACTER SET")) {
                return new SHOW_CHARACTER_SET();
            }

            if (sqlTrimUpper.startsWith("SHOW FUNCTION STATUS")) {
                return new SHOW_FUNCTION_STATUS();
            }

            if (sqlTrimUpper.startsWith("SELECT") && sqlTrimUpper.contains("FROM INFORMATION_SCHEMA")) {
                return new SELECT_INFORMATION_SCHEMA();
            }

            if (sqlTrimUpper.startsWith("SET NAMES")) {
                return new SET_NAMES();
            }

            JdbcStatement jdbcStatement = this.doParseSql(sql);
            log.info("#68 parse, sql=" + sql + ", jdbcStatement=" + jdbcStatement + ", this=" + this);
            return jdbcStatement;
        } catch (Throwable e) {
            log.error("#76 sql parse error, cause=" + e + ", sql=" + sql + ", this=" + this, e);

            throw new SQLException("#77 sql parse error, cause=" + e + ", sql=" + sql + ", this=" + this, e);
        }
    }

    protected JdbcStatement doParseSql(String sql) throws Throwable {
        log.error("#82 this=" + this + ", sql=" + sql);

        throw new RuntimeException("#83 this=" + this + ", sql=" + sql);
    }
}